/*
 * material.cpp
 *
 *  Created on: 13.06.2012
 *      Author: Caffeine
 */


#include "material.h"
#include <lampe/xml/IXMLFactoryEnvironment.h>
#include "irrxml.h"
#include <lampe/xml/IXmlNode.h>
#include <ISceneNodeAnimator.h>
#include <ISceneManager.h>
#include <IGPUProgrammingServices.h>
#include "../../shaders/layout.h"
#include <lampe/StringUtils.h>

namespace lampe{
namespace xml{

class MaterialFactory:public IIrrXmlNode{
private:
irr::video::E_MATERIAL_TYPE STRtoMaterialType(String s){
	s=lampe::str::toUpperCase(s);
	//s.make_upper();
	if (s=="SOLID") return irr::video::EMT_SOLID;
	if (s=="SOLID_2_LAYER") return irr::video::EMT_SOLID_2_LAYER;
	if (s=="LIGHTMAP") return irr::video::EMT_LIGHTMAP;
	if (s=="LIGHTMAP_ADD") return irr::video::EMT_LIGHTMAP_ADD;
	if (s=="LIGHTMAP_M2") return irr::video::EMT_LIGHTMAP_M2;
	if (s=="LIGHTMAP_M4") return irr::video::EMT_LIGHTMAP_M4;
	if (s=="LIGHTMAP_LIGHTING") return irr::video::EMT_LIGHTMAP_LIGHTING;
	if (s=="LIGHTMAP_LIGHTING_M2") return irr::video::EMT_LIGHTMAP_LIGHTING_M2;

	if (s=="LIGHTMAP_LIGHTING_M4") return irr::video::EMT_LIGHTMAP_LIGHTING_M4;
	if (s=="DETAIL_MAP") return irr::video::EMT_DETAIL_MAP;
	if (s=="SPHERE_MAP") return irr::video::EMT_SPHERE_MAP;
	if (s=="REFLECTION_2_LAYER") return irr::video::EMT_REFLECTION_2_LAYER;
	if (s=="TRANSPARENT_ADD_COLOR") return irr::video::EMT_TRANSPARENT_ADD_COLOR;

	if (s=="TRANSPARENT_ALPHA_CHANNEL") return irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;
	if (s=="TRANSPARENT_ALPHA_CHANNEL_REF") return irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
	if (s=="TRANSPARENT_VERTEX_ALPHA") return irr::video::EMT_TRANSPARENT_VERTEX_ALPHA;
	if (s=="TRANSPARENT_REFLECTION_2_LAYER") return irr::video::EMT_TRANSPARENT_REFLECTION_2_LAYER;
	if (s=="NORMAL_MAP_SOLID") return irr::video::EMT_NORMAL_MAP_SOLID;


	if (s=="NORMAL_MAP_TRANSPARENT_ADD_COLOR") return irr::video::EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR;
	if (s=="NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA") return irr::video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA;
	if (s=="PARALLAX_MAP_SOLID") return irr::video::EMT_PARALLAX_MAP_SOLID;
	if (s=="PARALLAX_MAP_TRANSPARENT_ADD_COLOR") return irr::video::EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR;
	if (s=="PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA") return irr::video::EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA;
	if (s=="ONETEXTURE_BLEND") return irr::video::EMT_ONETEXTURE_BLEND;
	return irr::video::EMT_SOLID;
}
public:
	MaterialFactory(irr::IrrlichtDevice*d):IIrrXmlNode(d){}
	virtual LAMPE_VECTOR_VENDOR<String> getProcessedTags(){
		LAMPE_VECTOR_VENDOR<String> list;
		list.push_back("material");
		return list;
	};

	virtual lampe::xml::TagResult tagHandlerBefor(lampe::xml::IXMLFactoryEnvironment*environment,lampe::xml::IXmlNode*node){
		if (!node->getParent()){
				node->setTag(0);
				return lampe::xml::STOP;
			}
			if (!node->getParent()->getTag()){
				node->setTag(0);
				return lampe::xml::STOP;
			}





			irr::scene::ISceneNode*obj=(irr::scene::ISceneNode*)node->getParent()->getTag();
			obj->grab();
			String mat_type=node->getAttString("type","SOLID");

            if (mat_type=="LayoutShader1") obj->setMaterialType((irr::video::E_MATERIAL_TYPE) video::createLayoutShader(getDevice()->getVideoDriver()->getGPUProgrammingServices(),1));
                else if (mat_type=="LayoutShader2") obj->setMaterialType((irr::video::E_MATERIAL_TYPE) video::createLayoutShader(getDevice()->getVideoDriver()->getGPUProgrammingServices(),2));
                    else if (mat_type=="LayoutShader3") obj->setMaterialType((irr::video::E_MATERIAL_TYPE) video::createLayoutShader(getDevice()->getVideoDriver()->getGPUProgrammingServices(),3));
                        else if (mat_type=="LayoutShader4") obj->setMaterialType((irr::video::E_MATERIAL_TYPE) video::createLayoutShader(getDevice()->getVideoDriver()->getGPUProgrammingServices(),4));
                            else if (mat_type=="LayoutShader5") obj->setMaterialType((irr::video::E_MATERIAL_TYPE) video::createLayoutShader(getDevice()->getVideoDriver()->getGPUProgrammingServices(),5));
								else obj->setMaterialType(STRtoMaterialType(mat_type));

			s32 mat_id=node->getAttS32("index",-1);
			if (mat_id<0){
				node->setTag(0);
				return lampe::xml::STOP;
			}

			irr::video::SMaterial*mat=&obj->getMaterial(mat_id);
			node->setTag(mat);
			return lampe::xml::NEXT;
	}

	virtual lampe::xml::TagResult tagHandlerAfter(lampe::xml::IXMLFactoryEnvironment*environment,lampe::xml::IXmlNode*node){
		if (node->getTag()){
				if (node->getParent() && node->getParent()->getTag()){
					irr::scene::ISceneNode*obj=(irr::scene::ISceneNode*)node->getParent()->getTag();
					obj->drop();
				}

				return lampe::xml::NEXT;
			}
			if (!node->getParent()){
				return lampe::xml::STOP;
			}
			if (!node->getParent()->getTag()){
				return lampe::xml::STOP;
			}

			irr::scene::ISceneNode*obj=(irr::scene::ISceneNode*)node->getParent()->getTag();
			for (irr::u32 i=0;i<obj->getMaterialCount();i++){
				irr::video::SMaterial*mat=&obj->getMaterial(i);
				node->setTag(mat);
				for (u32 j=0;j<node->getNodeCount();j++){
					environment->runNode(node->getNode(j));
				}
			}
			node->setTag(0);
			obj->drop();
			return lampe::xml::NEXT;
	}
};

}//namespace xml
}//namespace lampe


void regMaterial(lampe::xml::IXMLFactoryEnvironment*environment,irr::IrrlichtDevice*d){
	lampe::xml::IFactoryRecord*h=new lampe::xml::MaterialFactory(d);
	environment->registerHandler(h);
	h->drop();
}
